//
// Created by mio on 25-4-10.
//


#include "BufferReader.h"
#include "TcpSocket.h"

BufferReader::BufferReader(uint32_t initial_size)
{
    // buffer_.reserve(initial_size); // 使用 reserve 而不是 resize，只分配内存，不构造元素，效率稍高

    // 注意：reserve 只影响 capacity()，不影响 size()。
    // WritableBytes() 依赖 size()，所以 Read 函数中需要 resize。
    // 一个常见的替代做法是在构造时 resize(initial_size)。
    buffer_.resize(initial_size); // 为了让 WritableBytes() 初始化正确，这里改为 resize
}

BufferReader::~BufferReader()
{

}

int BufferReader::Read(int fd)
{
    /* 简单扩容 */
    // 获取当前缓冲区内可写空间的大小
    uint32_t size = WritableBytes();
    // 如果可写空间小于我们单次期望读取的最大量
    if (size < MAX_BYTES_PER_READ)
    {
        // 获取当前缓冲区已分配的总大小
        uint32_t bufferReadSize = buffer_.size();
        // 检查是否已达到或超过设定的最大缓冲区限制
        if (bufferReadSize > MAX_BUFFER_SIZE)
            return 0;

        // 扩展缓冲区：将缓冲区大小增加 MAX_BYTES_PER_READ
        // 注意：resize 可能会导致内存重新分配和数据拷贝，是潜在的性能点
        // 更优化的策略可能包括：
        // 1. 检查 (reader_index_ + WritableBytes()) 是否足够大，如果够大，
        //    可以将 [reader_index_, writer_index_) 的数据挪到缓冲区开头，
        //    然后调整 writer_index_ 和 reader_index_，腾出后面的空间。
        // 2. 使用环形缓冲区(circular buffer)。
        // 但当前实现是简单的线性增长。
        buffer_.resize(bufferReadSize + MAX_BYTES_PER_READ);
    }
    /* sockfd -> buffer */
    // 调用 recv 从 fd 读取数据，存入缓冲区中从 writer_index_ 开始的位置
    int bytes_read = ::recv(fd, BeginWrite(), MAX_BYTES_PER_READ, 0);
    // 如果成功读取到数据 (bytes_read > 0)
    if (bytes_read > 0)
        writer_index_ += bytes_read;

    return bytes_read;
}

uint32_t BufferReader::ReadAll(std::string& data)
{
    uint32_t size = ReadableBytes();
    if (size > 0)
    {
        // 使用 string::assign 从 Peek() 指向的位置拷贝 size 字节数据
        // Peek() 返回的是 reader_index_ 指向的位置
        data.assign(Peek(), size);
        writer_index_ = 0;
        reader_index_ = 0;
        // 注意：这里没有收缩 buffer_ 的大小，内存会保持增长后的状态。
    }
    else // 如果没有可读数据
    {
        data.clear(); // 确保输出 string 为空
    }
    // 返回读取的数据量
    return size;
}

uint32_t ReadUint32BE(char* data)
{
    uint8_t *p = (uint8_t*) data;
    uint32_t value = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
    return value;
}

uint32_t ReadUint32LE(char* data)
{
    uint8_t *p = (uint8_t*) data;
    uint32_t value = (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0];
    return value;
}

uint32_t ReadUint24BE(char* data)
{
    uint8_t *p = (uint8_t*) data;
    uint32_t value = (p[0] << 16) | (p[1] << 8) | p[2];
    return value;
}

uint32_t ReadUint24LE(char* data)
{
    uint8_t *p = (uint8_t*) data;
    uint32_t value = (p[2] << 16) | (p[1] << 8) | p[0];
    return value;
}

uint16_t ReadUint16BE(char* data)
{
    uint8_t *p = (uint8_t*) data;
    uint16_t value = (p[0] << 8) | p[1];
    return value;
}

uint16_t ReadUint16LE(char* data)
{
    uint8_t *p = (uint8_t*) data;
    uint16_t value = (p[1] << 8) | p[0];
    return value;
}